/*! @file radio.c
 * @brief This file contains functions to interface with the radio chip.
 *
 * @b COPYRIGHT
 * @n Silicon Laboratories Confidential
 * @n Copyright 2012 Silicon Laboratories, Inc.
 * @n http://www.silabs.com
 */

#include "compiler_defs.h"
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#include "radio_config.h"
/*****************************************************************************
 *  Local Macros & Definitions
 *****************************************************************************/

/*****************************************************************************
 *  Global Variables
 *****************************************************************************/
tRadioConfiguration RadioConfiguration = RADIO_CONFIGURATION_DATA;
tRadioConfiguration * pRadioConfiguration = &RadioConfiguration;
U8 customRadioPacket[RADIO_MAX_PACKET_LENGTH];
U8 Radio_Configuration_Data_Array[] = RADIO_CONFIGURATION_DATA_ARRAY;

#define JPG_SIZE           ( 49152 )  //3*1024*1024 / 64
#define RADIO_PACKET_LENGTH    56    //RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH
unsigned char JpgTransBuf1[ JPG_SIZE ][RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH];  //max jpg size: 6M
unsigned char JpgTransBuf2[ JPG_SIZE ][RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH];  //max jpg size: 6M
unsigned char JpgTransBuf3[ JPG_SIZE ][RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH - 3];
unsigned char (* pRecvBuf) [RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH];

extern inline void PI0_6_WRITE_BIT( int valueBit, int bSet) ;

#define  MAGIC_NUM  0XA3

#define PI_PROGAM_RX(bset)  		PI0_6_WRITE_BIT(2, bset)
extern 	void si446x_read_rx_fifo( U8 numBytes, U8* pRxData );
extern	   void si446x_write_tx_fifo( U8 numBytes, U8* pData );

/*****************************************************************************
 *  Local Function Declarations
 *****************************************************************************/
void vRadio_PowerUp(void);

/*!
 *  Power up the Radio.
 *
 *  @note
 *
 */
void vRadio_PowerUp(void)
{
  unsigned short wDelay = 0;

  /* Hardware reset the chip */
  si446x_reset();

  /* Wait until reset timeout or Reset IT signal */
  for (; wDelay < pRadioConfiguration->Radio_Delay_Cnt_After_Reset; wDelay++);
}

/*!
 *  Radio Initialization.
 *
 *  @author Sz. Papp
 *
 *  @note
 *
 */
void vRadio_Init(void)
{

  /* Power Up the radio chip */
 // vRadio_PowerUp();

  /* Load radio configuration */
  printf("vRadio_Init start \n");
  
  do{
    /* Error hook */
  //  LED4 = !LED4;
  

    /* Power Up the radio chip */
    vRadio_PowerUp();
	usleep(100000);
  }while (SI446X_SUCCESS != si446x_configuration_init(pRadioConfiguration->Radio_ConfigurationArray)) ;

  // Read ITs, clear pending ones
  si446x_get_int_status(0, 0, 0);
  printf("vRadio_Init end \n");
}

/*!
 *  Check if Packet received IT flag is pending.
 *
 *  @return   TRUE - Packet successfully received / FALSE - No packet pending.
 *
 *  @note
 *
 */
char gRadio_CheckReceived(void)
{
  U8 lCnt;

  if (SPI_IRQ == FALSE)
  {
    /* Read ITs, clear pending ones */
    si446x_get_int_status(0, 0, 0);

    if (Si446xCmd.GET_INT_STATUS.PH_PEND & SI446X_CMD_GET_INT_STATUS_REP_PACKET_RX_PEND_BIT)
    {
      /* Blink once LED3 as CRC OK or not enabled */
      /* Packet RX */
      si446x_read_rx_fifo(pRadioConfiguration->Radio_PacketLength, customRadioPacket);
      return TRUE;
    }
    if (Si446xCmd.GET_INT_STATUS.PH_PEND & SI446X_CMD_GET_INT_STATUS_REP_CRC_ERROR_BIT)
    {
      /* Reset FIFO */
      si446x_fifo_info(SI446X_CMD_FIFO_INFO_ARG_RX_BIT);
    }
  }
  return FALSE;
}

int jpgLen = 0;
unsigned int curPacket1 = 0, prePacket = 0, errPacket = 0 ;
extern int g_bRecv;


char jpgRecvFile1[] = "/data/lhg/recv1.jpg";
char jpgRecvFile2[] = "/data/lhg/recv2.jpg";
char jpgRecvFile[] = "/data/lhg/recv3.jpg";


int jpgWrite(unsigned char (* pWriteBuf) [RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH],   int size)
{
	int fp, fileLen1 = 0, fileLen2 = 0, bfindHead = 0;
	int wIndex = 0xffff , rIndex = 0, writeCount;
	prePacket = 0;
	errPacket = 0;
	//read file size

	while( rIndex < size )
	{
		if( pWriteBuf[rIndex][2] == MAGIC_NUM )
		{
			wIndex = pWriteBuf[rIndex][0]  | (pWriteBuf[rIndex ][1] << 8);  //packet header serial num
			if( wIndex != 0)
			{
				if( wIndex == 0xffff )
					break;
				if( wIndex > prePacket  && wIndex < size && wIndex < JPG_SIZE) 
		        {
		        	memcpy( JpgTransBuf3[wIndex - 1] , &pWriteBuf[rIndex][3] , RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH - 3 );
		        }
				if( wIndex != prePacket + 1 && wIndex < size && wIndex < JPG_SIZE) 
		        {
		        	errPacket += wIndex - prePacket - 1;
		            printf("err pre:%d, now:%d, errCount:%d \n", prePacket , wIndex, errPacket );
		        }
				prePacket = wIndex;

			}
			else  //packet header
			{
				if( !bfindHead){
					fileLen1 = pWriteBuf[0][3]    | (pWriteBuf[0][4] << 8) | (pWriteBuf[0][5] << 16)  | (pWriteBuf[0][6] << 24);
					fileLen2 = pWriteBuf[0][7]    | (pWriteBuf[0][8] << 8) | (pWriteBuf[0][9] << 16)  | (pWriteBuf[0][10] << 24);
					if( fileLen1 == fileLen2 )
					{
						bfindHead = 1;
					}
				}
			}

		}
		else
			printf("err magic ser:%d\n",rIndex);
		++rIndex;

	}
			
	printf("write :%d, total error:%d\n", size , errPacket);

	if((fp = open(jpgRecvFile, O_TRUNC | O_WRONLY | O_CREAT )) == -1 )
    {
        printf("open %s error\n", jpgRecvFile1 );
		return -1;
    }
	if( bfindHead ){
		printf("write data:%s,size:%d\n", jpgRecvFile, fileLen1);
		write( fp, JpgTransBuf3 , fileLen1);
	}
	else{
		printf("write data:%s,default size:%d\n", jpgRecvFile, size * (RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH - 3));
		write( fp, JpgTransBuf3 , size * ( RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH - 3) );
	}
    close(fp); 

	
	if( pWriteBuf == JpgTransBuf1)
	{
		if((fp = open(jpgRecvFile1, O_TRUNC | O_WRONLY | O_CREAT )) == -1 )
        {
            printf("open %s error\n", jpgRecvFile1 );
			return -1;
        }
	}
	else if ( pWriteBuf == JpgTransBuf2)
	{

		if((fp = open(jpgRecvFile2, O_TRUNC | O_WRONLY | O_CREAT )) == -1 )
	    {
	        printf("open %s error\n", jpgRecvFile2 );
			return -1;
	    }
	}
	else
		printf("error pWriteBuf \n");

	writeCount = write( fp, pWriteBuf , size * RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH );
	if( writeCount != size * RADIO_CONFIGURATION_DATA_RADIO_PACKET_LENGTH )
	{
        printf("FILE write error \n" );
		close(fp);  
		return -1;
    }
    close(fp);  
	return 0;
	
}


/*!
 *  Check if Packet received IT flag is pending.
 *
 *  @return   TRUE - Packet successfully received / FALSE - No packet pending.
 *
 *  @note
 *
 */
unsigned int recvIndex = 0;

char gRadio_CheckReceived_VariablePacket(void)
{

  if ( SPI_IRQ == FALSE)
  {
    /* Read ITs, clear pending ones */
    si446x_get_int_status(0u, 0u, 0u);

	if (Si446xCmd.GET_INT_STATUS.CHIP_PEND & SI446X_CMD_GET_CHIP_STATUS_REP_CMD_ERROR_PEND_BIT)
    {
      si446x_change_state(SI446X_CMD_CHANGE_STATE_ARG_NEW_STATE_ENUM_SLEEP);
		printf("reset \n");
	  // Reset FIFO 
      si446x_fifo_info(SI446X_CMD_FIFO_INFO_ARG_RX_BIT);
      
	  // State change to 
      si446x_change_state(SI446X_CMD_CHANGE_STATE_ARG_NEW_STATE_ENUM_RX);
    }

    // check the reason for the IT 
    if (Si446xCmd.GET_INT_STATUS.MODEM_PEND & SI446X_CMD_GET_INT_STATUS_REP_SYNC_DETECT_BIT)
    {
    // printf("it \n");
    }

    if (Si446xCmd.GET_INT_STATUS.PH_PEND & SI446X_CMD_GET_INT_STATUS_REP_PACKET_RX_PEND_BIT)
    {
      /* Read the length of RX_FIFO */
      si446x_fifo_info(0u);
      /* Packet RX */
	  if( Si446xCmd.FIFO_INFO.RX_FIFO_COUNT > 0)
	  {
	        si446x_read_rx_fifo(Si446xCmd.FIFO_INFO.RX_FIFO_COUNT, pRecvBuf[recvIndex ]);
			curPacket1 = pRecvBuf[ recvIndex ][0]  | (pRecvBuf[ recvIndex ][1] << 8);
			if( curPacket1 % 512== 0) {
				printf("p:%d\n", curPacket1);
			
#ifdef GPIO_BOARD
				PI_PROGAM_RX( 0 );
#endif
			}
			else if( curPacket1 % 512 == 256) {
				printf("p:%d\n", curPacket1);
#ifdef GPIO_BOARD
				PI_PROGAM_RX( 1 );
#endif
			}
			recvIndex += 1;
			if( curPacket1 == 0xffff  )
			{
				printf("total recv Packet:%d\n", recvIndex);
				jpgWrite( pRecvBuf , recvIndex  );
				if( pRecvBuf == JpgTransBuf2)
				{
					pRecvBuf = JpgTransBuf1;
				}
				else
					pRecvBuf = JpgTransBuf2;
				curPacket1 = 0;
				recvIndex = 0;
			}
	  	}
      	return TRUE;
    }

    if (Si446xCmd.GET_INT_STATUS.PH_PEND & SI446X_CMD_GET_INT_STATUS_REP_CRC_ERROR_BIT)
    {
      /* Reset FIFO */
      si446x_fifo_info(SI446X_CMD_FIFO_INFO_ARG_RX_BIT);
    }
  }

  return FALSE;
}



/*!
 *  Set Radio to RX mode, fixed packet length.
 *
 *  @param channel Freq. Channel
 *
 *  @note
 *
 */
  extern tRadioConfiguration * pRadioConfiguration;
void vRadio_StartRX(unsigned char channel)
{
  // Read ITs, clear pending ones
  si446x_get_int_status(0, 0, 0);

  /* Start Receiving packet, channel 0, START immediately, Packet length according to PH */
  si446x_start_rx(channel, 0u, pRadioConfiguration->Radio_PacketLength,
                  SI446X_CMD_START_RX_ARG_RXTIMEOUT_STATE_ENUM_NOCHANGE,
                  SI446X_CMD_START_RX_ARG_RXVALID_STATE_ENUM_RX,
                  SI446X_CMD_START_RX_ARG_RXINVALID_STATE_ENUM_RX );

  /* Switch on LED1 to show RX state */
 // vHmi_ChangeLedState(eHmi_Led1_c, eHmi_LedOn_c);
}
